/**
 * [简单线性回归](http://en.wikipedia.org/wiki/Simple_linear_regression)
 * 用于在坐标点集中寻找最佳拟合直线。本算法通过最小二乘法
 * 计算回归直线的斜率和截距。
 *
 * @param {Array<Array<number>>} data 二维数据数组，格式为
 * `[[0, 1], [2, 3]]`
 * @returns {Object} 包含回归直线斜率和截距的对象
 * @example
 * linearRegression([[0, 0], [1, 1]]); // => { m: 1, b: 0 }
 */
function linearRegression(data) {
    let m;
    let b;

    // 将数据长度存储在局部变量中以减少
    // 重复的对象属性查找
    const dataLength = data.length;

    // 当仅有一个数据点时，设置斜率为0
    // 截距取该点的y值
    if (dataLength === 1) {
        m = 0;
        b = data[0][1];
    } else {
        // 初始化求和变量，限定定义直线的
        // m（斜率）和b（截距）作用域
        let sumX = 0;
        let sumY = 0;
        let sumXX = 0;
        let sumXY = 0;

        // 使用局部变量存储坐标点值
        // 最小化对象属性访问
        let point;
        let x;
        let y;

        // 计算以下统计量的累加和：
        // x总和、y总和、x平方和、x*y乘积和
        //
        // 数学符号表示为 SS_x, SS_y, SS_xx, SS_xy
        for (let i = 0; i < dataLength; i++) {
            point = data[i];
            x = point[0];
            y = point[1];

            sumX += x;
            sumY += y;

            sumXX += x * x;
            sumXY += x * y;
        }

        // 根据最小二乘法公式计算斜率m
        m =
            (dataLength * sumXY - sumX * sumY) /
            (dataLength * sumXX - sumX * sumX);

        // 计算截距b
        b = sumY / dataLength - (m * sumX) / dataLength;
    }

    // 返回包含斜率和截距的对象
    return {
        m: m,
        b: b
    };
}

export default linearRegression;
